#ifndef __lm_conf_voice_wrapper_h__
#define __lm_conf_voice_wrapper_h__
#include "conf_wrapper_interface.h"
#include <list>

namespace lm {
	class ConfVoiceWrapper {
	public:
		class Observer {
		public:
			virtual void OnDeviceChange() {}
			virtual void OnDisconnectVoiceServer(int result) {}

		protected:
			Observer() {}
			virtual ~Observer() {}
		};

		void AddObserver(Observer* observer);
		void RemoveObserver(Observer* observer);

		int SetCodecType(LMVoiceCodecModes codec_type, LMVoiceDelayModes delay_mode = k120MSDelay);
		int GetCodecType(LMVoiceCodecModes& codec_type, LMVoiceDelayModes& delay_mode);

		int SetCodecTypeWithInputDevice(LMVoiceDeviceType input_type,
			LMVoiceCodecModes codec_type, LMVoiceDelayModes delay_mode, int rate);
		int GetCodecTypeWithInputDevice(LMVoiceDeviceType input_type,
			LMVoiceCodecModes& codec_type, LMVoiceDelayModes& delay_mode, int& rate);

		bool IsValidDelayMode(LMVoiceCodecModes codec_type, LMVoiceDelayModes delay_mode);

		int GetNumOfInputDevices(int& nums);
		int GetNumOfOutputDevices(int& nums);
		int GetInputDeviceName(int index, char* name, int name_size, char* guid, int guid_size);
		int GetOutputDeviceName(int index, char* name, int name_size, char* guid, int guid_size);
		int GetDefaultInputDeviceName(char* name, int name_size, char* guid, int guid_size);
		int GetDefaultOutputDeviceName(char* name, int name_size, char* guid, int guid_size);
		int GetCurrentInputDeviceName(char* name, int name_size, char* guid, int guid_size);
		int GetCurrentOutputDeviceName(char* name, int name_size, char* guid, int guid_size);

        int GetDefaultInputDeviceIndex(int& index);
        int GetDefaultOutputDeviceIndex(int& index);
        int GetCurrentInputDeviceIndex(int& index);
        int GetCurrentOutputDeviceIndex(int& index);
        
        int SetInputDevice(int index);
		int SetOutputDevice(int index);

		int SetInputVolume(unsigned int volume);
		int GetInputVolume(unsigned int& volume);
		int SetOutputVolume(unsigned int volume);
		int GetOutputVolume(unsigned int& volume);

		int GetInputVoiceLevel(unsigned int& level);
		int GetOutputVoiceLevel(const char* account, unsigned int& level);
		int GetOutputVoiceLevel(int node, unsigned int& level);

		int SetLoudspeakerStatus(bool enabled);
		int SetEcStatus(bool enabled, LMEcModes mode = kEcUnchanged);
		int SetNsStatus(bool enabled, LMNsModes mode = kNsUnchanged);
		int SetAgcStatus(bool enabled, LMAgcModes mode = kAgcUnchanged);
		int SetAecmMode(LMAecmModes mode = kAecmSpeakerphone, bool enableCNG = true);
		int SetVADStatus(bool enable, LMVadModes mode = kVadConventional, bool disableDTX = false);

		int GetLoudspeakerStatus(bool& enabled);
		int GetEcStatus(bool& enabled, LMEcModes& mode);
		int GetNsStatus(bool& enabled, LMNsModes& mode);
		int GetAgcStatus(bool& enabled, LMAgcModes& mode);
		int GetAecmMode(LMAecmModes& mode, bool& enabledCNG);
		int GetVADStatus(bool& enabled, LMVadModes& mode, bool& disabledDTX);

		int EnableDriftCompensation(bool enabled);
		int DriftCompensationEnabled(bool &enabled);

		int SetDelayOffsetMs(int offset);
		int DelayOffsetMs(int &offset);

		int EnableHighPassFilter(bool enabled);
		int IsHighPassFilterEnabled(bool &enabled);

		int EnableInput(bool enabled);
		int EnableOutput(bool enabled);

		int GetInputState(bool& enabled);
		int GetOutputState(bool& enabled);

		int DisablePlaybackInput(bool disabled);
		int DisableIPCameraInput(bool disabled);
		int DisableMediaPlayerInput(bool disabled);
		int DisableExternalDeviceInput(bool disabled);

		int DisablePlaybackInputLocalOutput(bool disabled);
		int DisableIPCameraInputLocalOutput(bool disabled);
		int DisableMediaPlayerInputLocalOutput(bool disabled);
		int DisableExternalDeviceInputLocalOutput(bool disabled);

		int GetDisablePlaybackInputState(bool& disabled);
		int GetDisableIPCameraInputState(bool& disabled);
		int GetDisableMediaPlayerInputState(bool& disabled);
		int GetDisableExternalDeviceInputState(bool& disabled);

		int GetDisablePlaybackInputLocalOutputState(bool& disabled);
		int GetDisableIPCameraInputLocalOutputState(bool& disabled);
		int GetDisableMediaPlayerInputLocalOutputState(bool& disabled);
		int GetDisableExternalDeviceInputLocalOutputState(bool& disabled);

		// Playout file locally
		int StartPlayingFileLocally(
			int& node,
			const char* fileName,
			bool loop = false,
			LMVoiceFileFormats format = kFileFormatPcm16kHzFile,
			float volumeScaling = 1.0,
			int startPointMs = 0,
			int stopPointMs = 0);

		int StartPlayingFileLocally(
			int& node,
			const void* stream, int stream_len,
			LMVoiceFileFormats format = kFileFormatPcm16kHzFile,
			float volumeScaling = 1.0,
			int startPointMs = 0, int stopPointMs = 0);

		int StopPlayingFileLocally(int node);

		int IsPlayingFileLocally(int node);

		// Use file as microphone input
		int StartPlayingFileAsMicrophone(
			const char* fileName,
			bool loop = false,
			bool mixWithMicrophone = false,
			LMVoiceFileFormats format = kFileFormatPcm16kHzFile,
			float volumeScaling = 1.0);

		int StartPlayingFileAsMicrophone(
			const void* stream, int stream_len,
			bool mixWithMicrophone = false,
			LMVoiceFileFormats format = kFileFormatPcm16kHzFile,
			float volumeScaling = 1.0);

		int StopPlayingFileAsMicrophone();

		int IsPlayingFileAsMicrophone();

		// Record speaker signal to file
		int StartRecordingPlayout(
			const char* account,
			const char* fileName,
			LMVoiceCodecModes codec = kUnknowVoiceCodec /*or ilbc*/,
			int maxSizeBytes = -1);

		int StartRecordingPlayout(
			const char* account,
			void* stream, int stream_len,
			LMVoiceCodecModes codec = kUnknowVoiceCodec /*or ilbc*/);

		int StopRecordingPlayout(const char* account);

		int StartRecordingPlayout(
			const char* fileName,
			LMVoiceCodecModes codec = kUnknowVoiceCodec /*or ilbc*/,
			int maxSizeBytes = -1);

		int StartRecordingPlayout(
			void* stream, int stream_len,
			LMVoiceCodecModes codec = kUnknowVoiceCodec /*or ilbc*/);

		int StopRecordingPlayout();

		// Record microphone signal to file
		int StartRecordingMicrophone(const char* fileName,
			LMVoiceCodecModes codec = kUnknowVoiceCodec/*or ilbc*/, int maxSizeBytes = -1);

		int StartRecordingMicrophone(void* stream, int stream_len,
			LMVoiceCodecModes codec = kUnknowVoiceCodec/*or ilbc*/);

		int StopRecordingMicrophone();

		int AddIPCamera(const LMIPCameraInfo* info, int camera_channel);
		int RemoveIPCamera(int identity, int camera_channel);

		int AddExternalRAWDataInputDevice(int sampleRate, int channel, int identity);
		int RemoveExternalRAWDataInputDevice(int identity);
		int IncomingExternalInputRAWData(int identity, const void* data, int data_len);

		int AddExternalRTPDataInputDevice(int identity);
		int RemoveExternalRTPDataInputDevice(int identity);
		int IncomingExternalInputRTPData(int identity, const void* data, int data_len, LMVoiceDelayModes delay_mode);

		//	for udp default kVoiceAdaptiveIO, tcp return -1
		int SetVoiceIOMode(LMVoiceIOModes mode);
		int GetVoiceIOMode(LMVoiceIOModes& mode);

	private:
		friend void CALLBACK FuncVoiceOnDisconnectVoiceServerCB(
			int result, void* clientdata);
		friend void CALLBACK FuncVoiceOnDeviceChangeCB(void* clientdata);

		void OnDisconnectVoiceServerCB(int result);
		void OnDeviceChangeCB();

		friend class ConfEngineWrapper;
		explicit ConfVoiceWrapper(native_object_t c_object);
		~ConfVoiceWrapper();

		native_object_t c_object_;

		typedef std::list<Observer*> ObserverList;
		ObserverList observer_list_;
	};
}

#endif //__lm_conf_voice_wrapper_h__